/*
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2006-2008 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_DVHD_VIDEO_ENCODER)

#include "umc_dv100_enc_720_60p_segment_reader.h"

namespace UMC
{

DV100_720_60p_SegmentReader::DV100_720_60p_SegmentReader(void)
{
}

DV100_720_60p_SegmentReader::~DV100_720_60p_SegmentReader(void)
{
}

static const Ipp32s MBLumaWidth = 16;
static const Ipp32s MBChromaWidth = 8;
static const Ipp32s MBHeight = 16;
static const Ipp32s MBHalfHeight = 8;
static const Ipp32s SBLumaWidth = 6 * MBLumaWidth;
static const Ipp32s SBChromaWidth = 6 * MBChromaWidth;

static
inline
Ipp32s GetMacroBlockOffsetInADevidedBlock(Ipp32s i, Ipp32s k, Ipp32s MBWidth, size_t Pitch)
{
    Ipp32s Row, Col;
    if(i%2 == 0)
    {
        Row = k / 6;
        Col = k % 6;
        return (Ipp32s) ((i/2) * 9 * MBHeight * Pitch +
                          Row * MBHeight * Pitch +
                          Col * MBWidth);
    }
    else
    {
        Row = (k + 3) / 6;
        Col = (k + 3) % 6;
        return (Ipp32s) (((i/2) * 9 * MBHeight + MBHeight * 4 ) * Pitch +
                         Row * MBHeight * Pitch  +
                         Col * MBWidth);
    }
}

static
void InitOffsets(size_t *YOffsets, size_t *UOffsets, size_t *VOffsets,
                 const size_t lPitches[], Ipp16s nDIFSeqNum, Ipp16s nVideoSegmentNum)
{
    Ipp32s MBNum;
    Ipp32s nChannelNum = nDIFSeqNum/10;
    nDIFSeqNum %= 10;

    Ipp32s s = nDIFSeqNum / 5;
    Ipp32s x = nDIFSeqNum % 5;
    Ipp32s t = (nVideoSegmentNum + 27*x) % 5;
    Ipp32s k = (nVideoSegmentNum + 27*x) / 5;
    Ipp32s h = nChannelNum;
    Ipp32s SuperBlockVertOrder[]=
    {
        (4*h + s + 2*t + 2) % 10, // a
        (4*h + s + 2*t + 6) % 10, // b
        (4*h + s + 2*t + 8) % 10, // c
        (4*h + s + 2*t + 0) % 10, // d
        (4*h + s + 2*t + 4) % 10  // e
    };
    Ipp32s SuperBlockHorzOrder[] = {2, 1, 3, 0, 4};

    size_t YPitch = lPitches[0];
    size_t UPitch = lPitches[1];
    size_t VPitch = lPitches[2];

    if(h>=2) h-=2;

    for(MBNum = 0; MBNum<5; MBNum++)
    {
        YOffsets[2*MBNum] = (SuperBlockHorzOrder[MBNum]*2 + h) * SBLumaWidth +
                            GetMacroBlockOffsetInADevidedBlock(SuperBlockVertOrder[MBNum], k, MBLumaWidth, YPitch);

        YOffsets[2*MBNum+1] = YOffsets[2*MBNum] + MBHalfHeight * YPitch;

        UOffsets[2*MBNum] = (SuperBlockHorzOrder[MBNum]*2 + h) * SBChromaWidth +
                            GetMacroBlockOffsetInADevidedBlock(SuperBlockVertOrder[MBNum], k, MBChromaWidth, UPitch);

        UOffsets[2*MBNum+1] = UOffsets[2*MBNum] + MBHalfHeight * UPitch;

        VOffsets[2*MBNum] = (SuperBlockHorzOrder[MBNum]*2 + h) * SBChromaWidth +
                            GetMacroBlockOffsetInADevidedBlock(SuperBlockVertOrder[MBNum], k, MBChromaWidth, VPitch);

        VOffsets[2*MBNum+1] = VOffsets[2*MBNum] + MBHalfHeight * VPitch;
    }
}

void DV100_720_60p_SegmentReader::ReadSegment(struct V_SEGMENT *lpVSegment, Ipp16s DIFSeqOrder, Ipp16s VSegmentOrder)
{
    size_t YOffsets[10], UOffsets[10], VOffsets[10];
    size_t Pitches[3];
    Pitches[0] = m_lpSourceFrame->GetPlanePitch(0);
    Pitches[1] = m_lpSourceFrame->GetPlanePitch(1);
    Pitches[2] = m_lpSourceFrame->GetPlanePitch(2);

    InitOffsets(YOffsets, UOffsets, VOffsets, Pitches, DIFSeqOrder, VSegmentOrder);

    ReadMacroBlocks(YOffsets, UOffsets, VOffsets, lpVSegment, m_lpSourceFrame);
}

}//namespace UMC

#endif // (UMC_ENABLE_DVHD_VIDEO_ENCODER)
